import { Socket } from 'socket.io-client';
import { Receiver } from './receiver';
import { ElMessage } from 'element-plus';
import { aesEncrypt } from './crypto';
import { Message_File } from './type';

/**
 * 客户端
 * ***
 * 用于主动发送消息和初始化Socket连接等基础操作
 */
export class Client extends Receiver {
  protected privateApplySuccessSet = new Set<string>();
  constructor(socket: Socket) {
    super(socket);
  }
  async init() {
    super.init();
  }
  async setUserId(userId: string) {
    this.userId = userId;
  }

  connectionSocket(friendIds: string[]) {
    //发送连接信息
    this.socket.emit('client-connection', this.userId, friendIds);
  }

  setName(name: string) {
    this.name = name;
  }
  getName() {
    return this.name;
  }
  agreeApply(senderId: string) {
    console.log('同意好友申请');
    this.socket.emit('agree-add-friend', senderId);
    window.electron.ipcRenderer.send('ipc:refresh-friend-list');
  }
  rejectApply(senderId: string) {
    console.log('拒绝好友申请');
    this.socket.emit('reject-add-friend', senderId);
    window.electron.ipcRenderer.send('ipc:refresh-friend-list');
  }

  //申请添加好友
  applyAddFriend(friendId: string): boolean {
    try {
      console.log('已触发');
      this.socket.emit('apply-add-friend', this.userId, friendId);
      return true;
    } catch (error) {
      return false;
    }
  }

  //私聊握手
  applyPrivateChat(friendId: string) {
    return new Promise<boolean>((resolve, _) => {
      const msg = ElMessage({
        type: 'warning',
        message: '正在连接中...',
        duration: 0,
        showClose: true
      });
      try {
        this.socket.emit(
          'apply-private-chat',
          {
            senderId: this.userId,
            dhPublicKey: this.dhPublicKey,
            rsaPublicKey: this.rsaPublicKey,
            sign: this.sign
          },
          friendId
        );
        window.electron.ipcRenderer.once(
          'ipc:key-negotiation-status',
          (_event, status) => {
            msg.close();
            console.log('客户端-获取的握手结果：', status);
            if (status) {
              resolve(true);
            } else {
              resolve(false);
            }
          }
        );
        window.electron.ipcRenderer.once('ipc:user-no-online', (_event, _) => {
          msg.close();
          ElMessage({
            type: 'warning',
            message: '好友不在线,无法通信',
            duration: 1000,
            showClose: true
          });
          resolve(false);
        });
      } catch (error) {
        console.error('applyPrivateChat函数：申请密钥协商异常：', error);
      }
    });
  }

  findPrivateSuccessSet(friendId: string) {
    return this.privateApplySuccessSet.has(friendId);
  }

  async sendChatMessage(message: string, friendId: string, friendName: string) {
    console.log('发送消息时接收的参数：', message, friendId, friendName);
    // return;
    console.log('已经点击了');
    const msg = ElMessage({
      type: 'success',
      message: '正在加密发送中...',
      duration: 0,
      showClose: true
    });
    try {
      const now = Date.now();
      const encryptedMessage = await aesEncrypt(friendId, message);
      console.log('私聊的消息：', encryptedMessage);
      this.socket.emit(
        'private-chat-message',
        friendId,
        encryptedMessage,
        now,
        this.name
      );
      // 缓存消息，如果发送成功，则触发保存事件，把消息保存到本地，如果发送失败，则丢弃该缓存
      window.electron.ipcRenderer.send('cache-own-message', {
        userId: this.userId,
        friendId: friendId,
        friendName: friendName,
        time: now,
        message: message
      });
      window.electron.ipcRenderer.once('cache-own-message', (_, status) => {
        console.log('消息缓存状态：', status);
      });
    } catch (error) {
      ElMessage({
        type: 'error',
        message: '私聊消息加密失败',
        duration: 2000,
        showClose: true
      });
      console.log(`私聊消息加密时出错：${error}`);
    } finally {
      msg.close();
    }
  }

  getFriendChatMessage(friendId: string) {
    return new Promise<Message_File>((resolve, reject) => {
      window.electron.ipcRenderer.send('get-chat-message', friendId);
      window.electron.ipcRenderer.once(
        'get-chat-message',
        (_, data: Message_File) => {
          if (data) {
            resolve(data);
          } else {
            reject(void 0);
          }
        }
      );
    });
  }

  deleteFriend(friendId: string, friendName: string) {
    this.socket.emit('delete-friend', this.userId, friendId, friendName);
  }

  getFriendsOnline(friendIds: string[]) {
    this.socket.emit('client-online-status', friendIds);
  }
}
